import traceback
from concurrent.futures import ThreadPoolExecutor
import random
import sys
import cv2
import os
import numpy as np
import json
import threading
import time

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import QPalette, QBrush, QPixmap
from PyQt5.QtCore import QTimer
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

try:
    from ui.pyqt_imshow import UI_ImageView
except:
    from pyqt_imshow import UI_ImageView
#from test_serial import write_bin

# from get_config import *
from common.utils import *

hv_layout = [QHBoxLayout, QVBoxLayout]


config = { # 暂时
    "captype": "hk",
    'password': '',
    'saoma_multi_match': 0,
    # 'key_2xxx': '123',
}
camnames = ['name1'] # （上层）函数调用时传递
confdef = {
    'saoma_multi_match': ['chk_conf', 0, '条码多次匹配'],# QCheckBox(name) 复选框  # key: [type, value, name]
    # 'key_2xxx': ['edit_conf', '123', '编辑框'],
}

def showimg(img_4, img):
    if isinstance(img_4, QLabel):
        if img is None:
            return 
        w1, h1 = img_4.width(), img_4.height()
        h, w = img.shape[:2]
        # print("H:",h)
        s = min(w1 / w, h1 / h)
        img = imresize(img, s)
        h, w = img.shape[:2]

        if len(img.shape) == 3:
            img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # opencv读取的bgr格式图片转换成rgb格式
        else:
            img = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB)
        # frame = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # opencv读取的bgr格式图片转换成rgb格式
        # pyqt5转换成自己能放的图片格式
        # .scaled(img_4.width(), img_4.height())  # 转换成QPixmap
        image = QImage(img.data, w, h, w * 3, QImage.Format_RGB888)
        jpg_out = QPixmap(image)
        #img_4.setScaledContents(True)
        img_4.setAlignment(Qt.AlignCenter)
        # print("setPixmap")
        img_4.setPixmap(jpg_out) #
        img_4.show()
    elif isinstance(img_4, UI_ImageView):
        img_4.set_img(img)
    # print("setPixmap end")


from PIL import Image,ImageDraw,ImageFont
def draw_text_cn(img,text,left,top,textcolor=(0,0,255),textsize=2):
    if isinstance(img,np.ndarray):
        img=Image.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
    draw=ImageDraw.Draw(img)
    fontstyle=ImageFont.truetype("font/simsun.ttc",textsize,encoding='utf-8')
    draw.text((left,top),text,textcolor,font=fontstyle)
    return cv2.cvtColor(np.asarray(img),cv2.COLOR_RGB2BGR)

def layout_it(obj, level):
    '''
    设置控件列表的布局
    例子： obj: [wdj1, [wdj2, wdj3]]，  level: 0
    [wdj2, wdj3]设为垂直布局， [wdj1,~]设为水平布局（level）

    :param obj: [wdj1, [wdj2, wdj3]]
    :param level: 0 h, 1 v
    :return: 布局对象
    '''
    if isinstance(obj, list):
        out = hv_layout[level % 2]()
        for x in obj:
            a = layout_it(x, level+1) #
            if 'Layout' in str(type(a)):
                out.addLayout(a)
            else:
                out.addWidget(a)

        return out

    return obj


def layout_itf1(obj, level, factor):
    if isinstance(obj, list):
        f = 0
        factor = factor if isinstance(factor, list) else [
            (factor+len(obj)-1)//len(obj) for j in obj] #
        out = hv_layout[level % 2]()
        for i in range(len(obj)):
            x = obj[i]
            a, f1 = layout_itf1(x, level+1, factor[i]) #
            if 'Layout' in str(type(a)):
                out.addLayout(a)
            else:
                out.addWidget(a)

            if f1 > 0:
                out.setStretchFactor(a, f1)

            f += f1

        return out, f

    return obj, factor


def layout_itf(obj, level, factor):
    return layout_itf1(obj, level, factor)[0]


def Work_thread(self):
    while self.h_thread_runing:
        aa = np.zeros([600, 600, 3], dtype='uint8')
        pos = (random.randint(1, 400), random.randint(1, 500))
        cv2.putText(aa, str(config['oktext']), pos,
                    cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 1)
        print(type(aa))
        if self.frame_callback is not None:
            self.frame_callback(aa)

        time.sleep(1)

# NewWidget是随便起的名字，QWidget是要重写的，继承给NewWidget
def make_grid(labs):
    grid = QGridLayout()
    dd = {}
    for i in range(len(labs)):
        la_cameraid = QLabel(labs[i])
        lb_cameraid = QLabel()
        la_cameraid.setBuddy(lb_cameraid)
        grid.addWidget(la_cameraid, i, 0)
        grid.addWidget(lb_cameraid, i, 1)
        lb_cameraid.setMinimumWidth(100)
        dd[labs[i]] = lb_cameraid

    return grid, dd


def make_grid_lay(gg):
    grid = QGridLayout()
    for row in range(len(gg)):
        for col in range(len(gg[row])):
            ctrl = gg[row][col]
            if isinstance(ctrl, str):
                ctrl = QLabel(ctrl)
            grid.addWidget(ctrl, row, col)
    return grid



from PyQt5.QtWidgets import QApplication  ,QWidget ,QFormLayout , QLineEdit, QLabel
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import QPalette, QBrush, QPixmap
from PyQt5.QtCore import QTimer
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
#from test_baozhu import *
import  time
# from get_config import *

class Washer():
    def wash(self):
        print('do some laundry stuff')



class DataStatistics(QWidget):
    #showSignal_data = pyqtSignal(list)

    def __init__(self, parent=None):  # 初始化 并定义界面
        super(DataStatistics, self).__init__(parent)
        self.setWindowTitle("数据统计")
        self.resize(1300, 900)

        self.setupUi()

        self.btn_clear_data = QtWidgets.QPushButton()
        self.btn_clear_data.setText("数据清零")
        self.btn_clear_data.setFixedWidth(200)

        fromlayout = QFormLayout()
        fromlayout.addRow(self.tableWidget)
        # fromlayout.addRow(self.btn_clear_data)
        self.setLayout(fromlayout)
        self.btn_clear_data.clicked.connect(self.clear_data)
        #self.showSignal_data.connect(self.test)
        self.threadrun = True

    def setupUi(self):
        self.tableWidget = QtWidgets.QTableWidget()
        self.tableWidget.setGeometry(QtCore.QRect(90, 70, 480, 260))
        # self.tableWidget.setMinimumSize(QtCore.QSize(480, 0))
        self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.tableWidget.setShowGrid(True)
        # self.tableWidget.setGridStyle(QtCore.Qt.DashLine)
        self.tableWidget.setGridStyle(QtCore.Qt.SolidLine)
        self.tableWidget.setObjectName("tableWidget")
        ncl = len(tongji)

        self.tableWidget.setRowCount(ncl)

        self.tableWidget.horizontalHeader().setVisible(True)
        self.tableWidget.horizontalHeader().setCascadingSectionResizes(False)
        self.tableWidget.horizontalHeader().setHighlightSections(True)
        self.tableWidget.horizontalHeader().setMinimumSectionSize(40)
        self.tableWidget.verticalHeader().setDefaultSectionSize(30)
        # self.tableWidget.verticalHeader().setStyleSheet("QHeaderView::section { background-color: rgb(123, 33, 201); }")
        # self.tableWidget.setStyleSheet("QTableWidget{ gridline-color: #000; }")

        header = self.tableWidget.horizontalHeader()
        aa = "日期 机型码 条码 结果".split()
        aa = aa + camnames
        # aa = aa + self.config['camnames']
        self.fields = aa
        self.data = []
        # print(aa)
        # aa.insert(0, '时间')
        # aa.insert(1, '机型码')
        # aa.insert(2, '条码')
        # aa.insert(3, '结果')
        self.tableWidget.setColumnCount(len(aa))
        self.tableWidget.setHorizontalHeaderLabels(aa)
        # header.setStyleSheet("QHeaderView::section { background-color: rgb(123, 33, 201); }")
        # header.setMinimumHeight(40)
        # header.sectionClicked.connect(self.order1)
        #header.setSectionResizeMode(QHeaderView.ResizeToContents)
        header.setSectionResizeMode(QHeaderView.Stretch)
        #hheader.setStretchLastSection(True)
        # header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
        # header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
        self.retranslateUi()
        # test_data_01 = ["2021_1_dvsvwsvwsfwfwfwrgwwwg", "ok", "ok", "ok", "ok", "ok", "ng", "ok"]
        # list_test_data = [test_data_01] * 8
        # list_test_data.append(["2021_1_", "ok", "ok", "ok", "ok", "ok", "ng", "ok"])
        # for data_t in list_test_data:
        #     self.add_data(data_t)
        return self.tableWidget

    def retranslateUi(self):  # 定义表格内容
        # ncl = len(tongji)
        # self.tableWidget.setColumnCount(5)
        # self.tableWidget.setRowCount(ncl)
        _translate = QtCore.QCoreApplication.translate
        __sortingEnabled = self.tableWidget.isSortingEnabled()
        self.tableWidget.setSortingEnabled(False)
        # def set_item_text(i, j, text):
        #     text1 = _translate("classRoom", str(text))
        #     item = QTableWidgetItem(text1)
        #     item.setTextAlignment(QtCore.Qt.AlignCenter)
        #     self.tableWidget.setItem(i, j, item)

        # for j, k in enumerate(tongji.keys()):
        #     v = tongji[k]
        #     set_item_text(j, 0, str(k))
        #     set_item_text(j, 1, str(v))

        # self.update()
        self.tableWidget.setRowCount(0)
        self.idx_h = 0
        return 0

    def add_data(self, data):
        self.data.append(data)
        row_count = self.tableWidget.rowCount()  # 返回当前行数(尾部)
        self.tableWidget.insertRow(row_count)  # 尾部插入一行
        for ix, data_cc in enumerate(data):
            # print('data_cc',data_cc)
            # item = LinkLabel(data_cc)
            item = QTableWidgetItem(data_cc)
            item.setTextAlignment(Qt.AlignCenter) 
            if data_cc == 'OK':
                #item.setForeground(QColor(0, 255, 0))
                item.setBackground(QColor(0, 255, 0))
            elif ix>=3:
                item.setBackground(QColor(255, 0, 0))
            self.tableWidget.setItem(self.idx_h, ix, item)

        self.idx_h += 1
        return 0

    def exptable(self):
        if len(self.fields) and len(self.data):
            import xlwt  # 引入xlwt模块
            book = xlwt.Workbook()
            sheet = book.add_sheet('sheet1')
            aa = get_time_stamp()
            file_name = QFileDialog.getSaveFileName(
                self, "save file", f"{out_img_p}\\{aa}.xls", "xls files(*.xls)")[0]

            if '.xls' not in file_name:
                return

            for col, field in enumerate(self.fields):
                sheet.write(0, col, field)

            for row, data in enumerate(self.data):
                for col, field in enumerate(data):
                    # format Date  这里13/16/18列是日期数据，所以做了单独的格式化处理

                    sheet.write(row + 1, col, field)

            book.save(file_name)
            # QMessageBox.information(self, '提示', '导出成功', QMessageBox.Yes | QMessageBox.Yes)
        else:
            QMessageBox.information(self, '提示', '无数据，请先查询', QMessageBox.Yes | QMessageBox.Yes)

        return 0

    def closeEvent(self, event):
        self.threadrun = False

    def clear_data(self):
        self.data = []
        #for x in tongji:
        #    tongji[x] = 0
        self.retranslateUi()


def test_DataStatistics():
    app = QApplication(sys.argv)
    # if machecinp() or _MachineCheck() == 0:
    ex = DataStatistics()
    ex.setWindowTitle(u'数据统计')
    ex.setWindowIcon(QIcon('ico.png'))
    ex.show()
    sys.exit(app.exec_())



class Ui_CamPaneld(QtWidgets.QLabel): # 一个相机窗口为QLabel
    def __init__(self, id, parent=None, cam_name = ''):
        super(Ui_CamPaneld, self).__init__(parent)
        # 信息显示
        ss = ''
        self.id = id
        self.cam_name = cam_name
        grid, self.dd = make_grid(ss.split())

        self.cic = QtWidgets.QLabel()
        self.cic.setStyleSheet(  # "QLabel{width:40px;height:40px;}"
            "QLabel{border-radius:10px}"
            "QLabel{background-color:#30AE4D}"
            "QLabel:hover{background-color:#309E4D}"
            "QLabel{padding:2px 4px}"
        )
        self.cic.setFixedSize(QSize(20, 20))
        # tt = f'相机{camnames[id]}'
        # tt = f"相机{self.cam_name}"
        tt = self.cam_name
        self.name = QtWidgets.QLabel(tt)
        downico = QApplication.style().standardIcon(51)
        self.down = QtWidgets.QPushButton()
        self.down.setIcon(downico)
        self.down.setFixedSize(QSize(20, 20))
        self.down.setToolTip('保存图片')
        self.down.setStyleSheet(
            "QPushButton{border-radius:10px}"
            # "QPushButton{background-color:#EE2C2A}"
            # "QPushButton:hover{background-color:#30AE4D}"
            "QPushButton:hover{border:1px solid #30AE4D}"
            "QPushButton:hover{border:1px solid #309E4D}"
            "QPushButton:pressed{background-color:#309E4D}"
            # "QPushButton{font:16px}"
            #"QPushButton{padding:2px 4px}"
        )
        self.isok = QtWidgets.QLabel('OK')
        self.isok.setFixedSize(QSize(32, 32))
        self.isok.setAlignment(Qt.AlignCenter)

        ss = '总数 合格 缺陷'
        gridlay_stat, self.dd_stat = make_grid(ss.split())
        self.grid_stat = QtWidgets.QLabel()
        self.grid_stat.setLayout(gridlay_stat)
        self.grid_stat.setStyleSheet("background-color:#303463;")
        self.grid_stat.setMaximumWidth(150)
        lay = layout_it([self.cic, self.name, self.down], 0)

        # self.grid.setSpacing(10)
        #self.grid.setContentsMargins(10, 10, 10, 10)
        self.setObjectName("CamPaneld")
        # self.lab = QtWidgets.QLabel()
        # self.lab = UI_ImageView()
        self.lab = UI_ImageView(cam_name=cam_name)

        #lab.setFixedSize(2*641, 2*481)
        self.lab.setAutoFillBackground(False)
        #lay = layout_it([[[lay, grid], self.grid_stat], self.lab], 1)
        lay = layout_it([lay, grid, self.lab], 1)
        # lay.setSpacing(0)
        #lay.setContentsMargins(20, 20, 20, 20)
        # self.lab.setMinimumHeight(300)
        lay.setStretchFactor(self.lab, 2)
        self.setLayout(lay)
        self.setMinimumHeight(400)
        self.setStyleSheet("font-size:16px;"
                           "background-color:#2D2F58;"
                           "font-size:16px;"
                           "background-color:#2D2F58;"
                           "border-radius:10px;"
                           )

    def contextMenuEvent(self, event): # 点击右键 触发函数
        self.useRoRect = True
        menu = QMenu()
        aa = [0, 90, 180, 270]
        rotActions = [menu.addAction(f"旋转{x}度") for x in aa]
        itemactions = []
        if 0:
            menu.addSeparator()
            itemactions = [menu.addAction(x) for x in self.labels]

        action = menu.exec_(self.mapToGlobal(event.pos()))
        point = event.pos()
        #if action == addRectAction:            self.addItem(pos, False)
        #if self.useRoRect and action == addRoRectAction:
        #    self.addItem(pos, True)
        cam_rot = config['cam_rot']
        for i, a in enumerate(rotActions):
            if action == a:
                cam_rot[self.id] = aa[i]
                config_save()



class Ui_StatPaneld(QtWidgets.QLabel):
    def __init__(self, id, parent=None):
        super(Ui_StatPaneld, self).__init__(parent)
        # 信息显示
        # ss = '物料号 检测结果'
        # grid, self.dd = make_grid(ss.split())
        #
        # self.cic = QtWidgets.QLabel()
        # self.name = QtWidgets.QLabel(f'停线已经开启')
        # downico = QApplication.style().standardIcon(51)
        # self.down = QtWidgets.QPushButton()
        # self.down.setIcon(downico)
        # self.down.setFixedSize(QSize(20, 20))
        # self.down.setToolTip('save image')
        # self.down.setStyleSheet(
        #     "QPushButton{border-radius:10px}"
        #     # "QPushButton{background-color:#EE2C2A}"
        #     # "QPushButton:hover{background-color:#30AE4D}"
        #     "QPushButton:hover{border:1px solid #30AE4D}"
        #     "QPushButton:hover{border:1px solid #309E4D}"
        #     "QPushButton:pressed{background-color:#309E4D}"
        #     # "QPushButton{font:16px}"
        #     #"QPushButton{padding:2px 4px}"
        # )
        # self.isok = QtWidgets.QLabel('OK')
        # self.isok.setFixedSize(QSize(32, 32))
        # self.isok.setAlignment(Qt.AlignCenter)
        # self.set_ng(0)
        #
        # ss = '总数 合格 缺陷'
        # gridlay_stat, self.dd_stat = make_grid(ss.split())
        # if '缺陷' in self.dd_stat:
        #     self.dd_stat['缺陷'].setStyleSheet('color: rgb(255, 0, 0)')
        # self.grid_stat = QtWidgets.QLabel()
        # self.grid_stat.setLayout(gridlay_stat)
        # self.grid_stat.setStyleSheet("background-color:#303463;")
        # self.grid_stat.setMaximumWidth(150)
        # # lay = layout_it([self.cic, self.name, self.isok], 0)
        # lay = layout_it([self.cic, self.name], 0) # 去除ok label; 0513
        #
        # # self.grid.setSpacing(10)
        # #self.grid.setContentsMargins(10, 10, 10, 10)
        # self.setObjectName("CamPaneld")
        # #self.lab = QtWidgets.QLabel()
        # #lab.setFixedSize(2*641, 2*481)
        # # self.lab.setAutoFillBackground(False)
        # lay = layout_it([[lay, grid], self.grid_stat], 0)
        # # lay.setSpacing(0)
        # #lay.setContentsMargins(20, 20, 20, 20)
        # # self.lab.setMinimumHeight(100)
        # #lay.setStretchFactor(self.lab, 2)
        # self.setLayout(lay)
        # self.setMinimumHeight(100)
        # self.setStyleSheet("font-size:16px;"
        #                    "background-color:#2D2F58;"
        #                    "font-size:16px;"
        #                    "background-color:#2D2F58;"
        #                    "border-radius:10px;"
        #                    )
        # self.update_ui()
        self.setFont(QFont('Arial', 16))  # 设置字体和大小
        self.setStyleSheet('margin-top: 10px; margin-bottom: 10px;')  # 设置上下间距
        self.setText('产品型号: ')
        self.show_product_type('12345')
    def show_product_type(self, pt=''):
        self.setText(f'产品型号: {pt}')

    # def update_ui(self):
    #     ss = '停线未开启'
    #     color = '#30AE4D'
    #     hovercolor = '#309E4D'
    #     if 1 or config['stopline']:
    #         # ss = '停线已经开启'
    #         ss = '福霸汽车天线检测'
    #         color = '#DD5C2A'
    #         hovercolor = '#DD2C2A'
    #     self.name.setText(ss)
    #     self.cic.setStyleSheet(  # "QLabel{width:40px;height:40px;}"
    #         "QLabel{border-radius:10px}"
    #         "QLabel{background-color:%s}"
    #         "QLabel:hover{background-color:%s}"
    #         "QLabel{padding:2px 4px}" % (color, hovercolor)
    #     )
    #     self.cic.setFixedSize(QSize(20, 20))
    #
    # def update_tongji1(self):
    #     cnt_all = tongji['cnt_all']
    #     cnt_ng = tongji['cnt_ng']
    #     cnt_ok = tongji['cnt_ok']
    #
    #     self.dd_stat['总数'].setText(f'{cnt_all}')
    #     if cnt_all == 0:
    #         cnt_all = 1
    #     okrate = cnt_ok*100/cnt_all
    #     if 'tongji_ai' in config:
    #         if config['tongji_ai'] and okrate==100:
    #             #okrate = 99.5
    #             pass
    #     ngrate = 100-okrate
    #     self.dd_stat['缺陷'].setText(
    #         f'{cnt_ng} {ngrate:.1f}%')
    #     self.dd_stat['合格'].setText(
    #         f'{cnt_ok} {okrate:.1f}%')
    #
    # def update_tongji(self, li):
    #     # end, product= li[:2]
    #     end, product, show_str = li[:3]
    #     # self.stat_pad.dd_stat['缺陷']
    #     self.dd['物料号'].setText(product)
    #     tt = 'NG' if end else 'OK'
    #     # self.dd['检测结果'].setText(tt) #
    #     self.dd['检测结果'].setText(tt)  #/
    #     # self.dd['检测结果'].setText(show_str)  #
    #     self.set_ng(end)
    #     if end == 0 or end == 1:
    #         update_tongji(end)
    #         self.update_tongji1()
    #
    #
    # def set_ng(self, b):
    #     tt = 'NG' if b else 'OK'
    #     color = '#DD2C2A' if b else '#30AE4D'
    #     self.isok.setText(tt)
    #     self.isok.setStyleSheet(
    #         "QLabel{border-radius:3px}"
    #         "QLabel{background-color:%s}"
    #         "QLabel{font:24px bold}" % (color)
    #         #"QLabel{padding:2px 4px}"
    #     )



def make_pad(name, lay):
    #pad = QtWidgets.QLabel()
    pad = QtWidgets.QGroupBox(name)
    pad.setLayout(lay)
    return pad


class SettingSlider(QtWidgets.QWidget):
    def __init__(self, name, config_text):
        super().__init__()
        self.config_text = config_text
        self.lab = QLabel(name)
        self.slider_thd = QSlider(Qt.Horizontal)
        self.slider_thd.valueChanged.connect(self.config_valueChange)
        self.name = name
        x = config[self.config_text]
        #self.slider_thd.setValue(x)
        #check = QCheckBox(config_text)
        # check.stateChanged.connect(self.config_valueChange)
        lay = layout_it([self.lab, self.slider_thd], 0)
        self.setLayout(lay)

    def set(self, config):
        self.slider_thd.setValue(config[self.config_text])

    def config_valueChange(self):
        x = self.slider_thd.value()
        config[self.config_text] = x
        s = f"{self.name}:{int(x):3d}"
        self.lab.setText(s)
        # self.update()
        config_save()


class SettingCheckBox(QtWidgets.QWidget): #
    def __init__(self, type_value_showname_list = [], ui_handle=None):
        '''
        复选框
        '''
        super().__init__()
        self.type_value_showname_list = type_value_showname_list  # 需要址传递
        self.check = QCheckBox(self.type_value_showname_list[2])
        self.check.stateChanged.connect(self.config_valueChange_solt) # 槽

        # x = config[self.config_text]
        self.check.setChecked(type_value_showname_list[1])

        lay = layout_it([self.check], 0)
        self.setLayout(lay)
        self.ui_handle = ui_handle

    def set(self, config): #
        self.check.setChecked(config[self.config_text])

    def config_valueChange_solt(self): # obj 2 value
        self.type_value_showname_list[1] = self.check.checkState() # 0 or 1
        print(self.type_value_showname_list)
        print(self.ui_handle.ui_config)

class SettingComboBox(QtWidgets.QWidget):
    '''
    下拉框
    '''
    def __init__(self, type_value_showname_items_list=[]):
        super().__init__()
        self.type_value_showname_items_list = type_value_showname_items_list
        self.lab = QLabel(type_value_showname_items_list[2])
        self.combo = QComboBox()
        # if isinstance(items, str):
        #     items = items.split('|')
        self.combo.addItems(type_value_showname_items_list[-1])
        self.combo.currentIndexChanged.connect(self.obj2value_slot)

        #self.combo.setChecked(x)
        self.combo.setCurrentIndex(type_value_showname_items_list[1])
        #combo = QCheckBox(config_text)
        # combo.stateChanged.connect(self.config_valueChange)
        lay = layout_it([self.lab, self.combo], 0)
        self.setLayout(lay)

    # def set(self, config):
    #     x = int(config[self.config_text])
    #     self.combo.setCurrentIndex(x)

    def obj2value_slot(self):
        x = self.combo.currentIndex()
        self.type_value_showname_items_list[1] = x
        print(self.type_value_showname_items_list)
        # todo save to disk


class SettingTextsListEdit(QtWidgets.QWidget):
    def __init__(self, name, config_text):
        super().__init__()
        self.config_text = config_text
        self.lab = QLabel(name)
        self.edit = QTextEdit()
        # self.edit.setEchoMode(QLineEdit.PasswordEchoOnEdit)
        self.edit.textChanged.connect(self.config_valueChange)
        self.name = name
        x = config[self.config_text]
        self.edit.setText('\n'.join(x))
        #check = QCheckBox(config_text)
        # check.stateChanged.connect(self.config_valueChange)
        lay = layout_it([self.lab, self.edit], 0)
        self.setLayout(lay)

    def set(self, config):
        self.edit.setText('\n'.join(config[self.config_text]))

    def config_valueChange(self):
        x = self.edit.toPlainText()
        xx = x.split('\n')
        xx = [x.strip() for x in xx]
        config[self.config_text] = xx
        # self.lab.setText(s)
        # self.update()
        config_save()


class SettingLineEdit(QtWidgets.QWidget):
    def __init__(self, name, config_text):
        super().__init__()
        self.config_text = config_text
        self.lab = QLabel(name)
        self.edit = QLineEdit()
        # self.edit.setEchoMode(QLineEdit.PasswordEchoOnEdit)
        self.edit.textChanged.connect(self.config_valueChange)
        self.name = name
        x = str(config[self.config_text])
        self.edit.setText(x)
        #check = QCheckBox(config_text)
        # check.stateChanged.connect(self.config_valueChange)
        lay = layout_it([self.lab, self.edit], 0)
        self.setLayout(lay)

    def set(self, config):
        self.edit.setText(config[self.config_text])

    def config_valueChange(self):
        x = self.edit.text()
        config[self.config_text] = x
        # self.lab.setText(s)
        # self.update()
        config_save()


class SettingFileSelect(QtWidgets.QWidget):
    def __init__(self, name, config_text):
        super().__init__()
        self.config_text = config_text
        #self.lab = QLabel(name)
        self.pushButton = QPushButton(name)
        self.pushButton.clicked.connect(self.getfile)
        self.lineEdit = QLineEdit()
        # self.lineEdit.setEchoMode(QLineEdit.PasswordEchoOnEdit)
        #self.lineEdit.textChanged.connect(self.config_valueChange)
        self.name = name
        x = config[self.config_text]
        self.lineEdit.setText(x)
        #check = QCheckBox(config_text)
        # check.stateChanged.connect(self.config_valueChange)
        lay = layout_it([self.pushButton, self.lineEdit], 0)
        self.setLayout(lay)

    def set(self, config):
        self.lineEdit.setText(config[self.config_text])

    def getfile(self):
        dir = QFileDialog()      # 创建文件对话框
        # dir.setDirectory("D:\\")   # 设置初始路径为D盘
        dir.setDirectory(".\\")   # 设置初始路径为D盘
        # 设置只显示文本文件
        dir.setNameFilter("图片文件(*.jpg)")
        if dir.exec_():    # 判断是否选择了文件
            x = dir.selectedFiles()[0]
            self.lineEdit.setText(x)     # 将选择的文件显示在文本框中
            config[self.config_text] = x
            # self.lab.setText(s)
            # self.update()
            config_save()
            
    def config_valueChange(self):
        x = self.lineEdit.text()
        config[self.config_text] = x
        # self.lab.setText(s)
        # self.update()
        config_save()

class Ui_Setting(QDialog): # todo 可层级设置

    def __init__(self, parent=None, kv_dict={}, ui_handle=None):
        super(Ui_Setting, self).__init__(parent)
        #dd = {}
        li = []
        # lineedit = SettingLineEdit('新密码', 'password')
        # li.append(lineedit)
        try:
            # 设置界面的 子控件
            # for x in confdef.keys():
            for key, type_value_showname_list in kv_dict.items():
                t = type_value_showname_list[0]
                if t == 'chk_conf':
                    # _, v, name = confdef[x]
                    check_ui_handle = SettingCheckBox(type_value_showname_list, ui_handle) # show_name, key
                    #dd[name] = slider
                    li.append(check_ui_handle)
                # elif t == 'thd_conf':
                #     _, v, minv, maxv, name = confdef[x]
                #     slider = SettingSlider(name, x)
                #     slider.slider_thd.setMinimum(minv)
                #     slider.slider_thd.setMaximum(maxv)
                #     slider.slider_thd.setValue(config[x])
                #     #dd[name] = slider
                #     li.append(slider)
                # elif t == 'edit_conf':
                #     _, v, name = confdef[x]
                #     check = SettingLineEdit(name, x)
                #     #dd[name] = slider
                #     li.append(check)
                elif t == 'combo_conf':
                    # _, v, name,items = confdef[x]
                    # check = SettingComboBox(name, x, items)
                    check = SettingComboBox(type_value_showname_list)
                    #dd[name] = slider
                    li.append(check)
                # elif t == 'file_conf':
                #     _, v, name = confdef[x]
                #     check = SettingFileSelect(name, x)
                #     #dd[name] = slider
                #     li.append(check)
                else:
                    print(f'Ui_Setting error: {x}:{confdef[x]}')
            #pad = make_grid_lay(li)
            k = 20
            self.li = li
            if len(li)>k:
                n = (len(li)+k-1)//k
                k = (len(li)+n-1)//n
                li1 = [li[i*k:(i+1)*k] for i in range(n)]
                pad = layout_it(li1, 0)
            else:
                pad = layout_it(li, 1)
            self.setLayout(pad)
            self.setWindowTitle('设置')
            # self.setWindowIcon(QtGui.QIcon('D:/code/git/ywlydd/py/xingo/logo.png'))
        except:
            print(traceback.format_exc())

    def config_updateUI(self, config):
        import copy
        for x in self.li:
            x.set(config)
        self.update()
        return 0



def listdirdir(pa):
    li = os.listdir(pa)
    #li = [f'{pa}/{x}' for x in li]
    #li = [x for x in li if os.path.isdir(x)]
    li = [x for x in li if os.path.isdir(f'{pa}/{x}')]
    return li

def time_fmt(pp):
    #pp = '_'.join(pp.split('_')[:2])
    y = pp[:4]
    m = pp[4:6]
    d = pp[6:8]
    h = pp[9:11]
    mm = pp[11:13]
    ss = pp[13:15]
    pp = f'{y}/{m}/{d}_{h}:{mm}'
    return pp

def get_ppp_fns(pp, li0):
    ppp = [str('') if x<4 else 'OK' for x in range(4+len(cam_ips))]
    fns = [['', ''] for x in cam_ips]
    allok = 'OK'
    jxinma = ''
    tiaoma = ''
    ppp[0] = time_fmt(pp)
    for fn in li0:
        tiaoma0, index, end = fn.split('_')[-4:-1]
        if index not in '0123456789':
            tiaoma0 = index
            index = os.path.split(fn)[1].split('_')[1]
            
        index1 = 4 + int(index)
        if end not in ['OK']:
            allok = 'NG'
        ppp[4 + int(index)] = end
        if 'NOREAD' not in tiaoma0.upper():
            tiaoma = tiaoma0
        t = 0
        if '_ret' in fn:
            t = 1
        fns[int(index)][t] = fn
        # ppp[pp].append(fn)

    if 'NOREAD' in tiaoma.upper():
        allok = 'NG'
    else:
        jxinma = tiaoma[6:11]
        
    ppp[1] = jxinma
    ppp[2] = tiaoma
    ppp[3] = allok
    return ppp, fns

def find_file_by_time(ss, time0, time1, ngok):
    time00 = time0.split('_')[0]
    time10 = time1.split('_')[0]
    lidays = listdirdir(out_img_p)
    lidays = [x for x in lidays if time00<=x and x<=time10]
    ngok = ngok.lower()
    for day in lidays:
        outp0 = f'{out_img_p}/{day}'
        li = listdirdir(outp0)
        li = [x for x in li if x.lower() in ngok]
        aa = []
        for fn0 in li:
            pa0 = f'{outp0}/{fn0}'
            aa += listdirdir(pa0)
        aa = list(set(aa))
        aa.sort()
        for pp in aa:
            aa = '_'.join(pp.split('_')[:2])
            if aa <= time1 and aa >= time0:
                li0 = []
                for fn0 in li:
                    pa1 = f'{outp0}/{fn0}/{pp}'
                    li1 = listdir(pa1, '.jpg')
                    li0 += [f'{pa1}/{x}' for x in li1]
            
                ppp, fns = get_ppp_fns(pp, li0)
                if ss is not None:
                    if ss.running == 0:
                        return 0
                    ss.showSignal.emit([pp, ppp, fns])
    
    return 0


def find_file_by_time_hf(ss, time0, time1, ngok):
    time00 = time0.split('_')[0]
    time10 = time1.split('_')[0]
    lidays = listdirdir(out_img_p)
    ngok = ngok.lower()
    lidays = [x for x in lidays if 'cam' in x and x[-2:] in ngok]
    for day in lidays:
        outp0 = f'{out_img_p}/{day}'
        li = listdirdir(outp0)
        li = [x for x in li if time00<=x and x<=time10]
        aa = []
        for fn0 in li:
            pa0 = f'{outp0}/{fn0}'
            aa += listdirdir(pa0)
        aa = list(set(aa))
        aa.sort()
        for pp in aa:
            aa = '_'.join(pp.split('_')[:2])
            if aa <= time1 and aa >= time0:
                li0 = []
                for fn0 in li:
                    pa1 = f'{outp0}/{fn0}/{pp}'
                    li1 = listdir(pa1, '.jpg')
                    li0 += [f'{pa1}/{x}' for x in li1]
            
                ppp, fns = get_ppp_fns(pp, li0)
                if ss is not None:
                    if ss.running == 0:
                        return 0
                    ss.showSignal.emit([pp, ppp, fns])
    
    return 0

def show_imgs(imglabs, li):
    # pa = r'D:\data\gree_zhuhai\2_d\images\train'
    # li = listdir(pa, '.jpg .png')
    # li = [f'{pa}/{x}' for x in li]
    for i in range(len(imglabs)):
        if i < len(li):
            if not os.path.exists(li[i]):
                continue
            try:
                img = cv_imread(li[i])
            except Exception as e:
                continue
            if i==0:
                img = draw_text_cn(img, "原图", 100, 100, (0, 0, 255), 48)
            showimg(imglabs[i], img)


def label_set_ng(lab, b):
    tt = 'NG' if b else 'OK'
    # tt = '不合格' if b else '合格'
    color = '#DD2C2A' if b else '#30AE4D'
    lab.setText(tt)
    lab.setAlignment(Qt.AlignCenter)
    lab.setStyleSheet(
        "QLabel{border-radius:3px}"
        "QLabel{background-color:%s}"
        # "QLabel{font:24px bold}"
        % (color)
        # "QLabel{padding:2px 4px}"
    )


class Ui_DataBase(QtWidgets.QWidget):
    showSignal = pyqtSignal(list)

    def __init__(self, ss=None, parent=None):
        super(Ui_DataBase, self).__init__(parent)

        # self.face_recong = face.Recognition()
        self.set_ui()

    def set_ui(self):
        #self.imglabs = [QLabel() for i in range(2)]
        self.imglabs = [UI_ImageView() for i in range(2)]

        ss = camnames
        gridret, self.dd = make_grid(camnames)
        for x in self.dd:
            b = random.random() > 0.5
            label_set_ng(self.dd[x], b)

        self.setWindowTitle('数据查询')
        self.datastt = DataStatistics()

        self.btn_query = QtWidgets.QPushButton(u'查询')
        self.btn_query.clicked.connect(self.query)
        self.btn_exptable = QtWidgets.QPushButton(u'导出表格')
        self.btn_exptable.clicked.connect(self.datastt.exptable)
        self.btn_data = QtWidgets.QPushButton(u'质量闭环数据')
        btns = [self.btn_query, self.btn_exptable, self.btn_data]

        time0 = QDateTime.currentDateTime()
        time0 = time0.addDays(-2)
        self.start_dateTimeEdit = QDateTimeEdit(time0, self)
        # self.start_dateTimeEdit.dateTimeChanged.connect(lambda: print('DateTime Changed!'))
        self.start_dateTimeEdit.setCalendarPopup(True)

        self.end_dateTimeEdit = QDateTimeEdit(QDateTime.currentDateTime(), self)
        # self.end_dateTimeEdit.dateTimeChanged.connect(lambda: print('DateTime Changed!'))
        self.end_dateTimeEdit.setCalendarPopup(True)

        self.cbox_query_type = QComboBox(self)
        self.qname = '全部 合格 不合格'.split()
        self.qname1 = 'OKNG OK NG'.split()
        for x in self.qname:
            self.cbox_query_type.addItem(x)


        self.edit_tiaoma = QLineEdit(self)
        #self.edit_chenpingma = QLineEdit(self)
        self.aaa = [
            ['起始时间：', self.start_dateTimeEdit],
            ['结束时间：', self.end_dateTimeEdit],
            ['查询类型：', self.cbox_query_type],
            ['条码：', self.edit_tiaoma],
            #['成品码：', self.edit_chenpingma],
        ]
        self.grid1 = make_grid_lay(self.aaa)
        self.grid_ret = QtWidgets.QGroupBox('结果')
        self.grid_ret.setLayout(gridret)
        #aa = [self.imglabs, [[self.grid1, btns], self.grid_ret, self.datastt]]
        aa = [self.imglabs, [[self.grid1, btns], self.datastt]]
        lay = layout_itf(aa, 1,
                         [5, [0, 2]])
        self.setLayout(lay)
        self.showSignal.connect(self.show_fun)
        self.ppp = []
        self.fns = []
        # self.pppp = []
        def netItem_clicked(iy, ix):
            index = ix - 4
            if index >= 0 and iy<len(self.fns):
                if index<len(self.fns[iy]):
                    fn2 = self.fns[iy][index]
                    print(iy, ix, fn2)
                    # dialog = ShowInfo(self, self.out, irow)
                    # dialog.setWindowTitle("详细信息")
                    # dialog.setWindowModality(Qt.ApplicationModal)
                    # dialog.exec_()
                    show_imgs(self.imglabs, fn2)
            return 0

        self.datastt.tableWidget.cellClicked.connect(netItem_clicked)
        self.ret = None
        self.running = 0
        self.pool = BoundThreadPoolExecutor(qsize=8, max_workers=8)
        self.query()

    def show_fun(self, li):
        # print("get single:",data)return
        pp, ppp, fns = li[:3]
        self.ppp.append(ppp)
        self.fns.append(fns)
        self.datastt.add_data(ppp)
        return 0

    def query(self):
        if self.ret is not None:
            self.running = 0
            ret = self.ret.result()
        self.ppp = []
        self.fns = []
        self.datastt.clear_data()
        fmt = "yyyyMMdd_hhmmss"
        time0 = self.start_dateTimeEdit.dateTime().toString(fmt)
        time1 = self.end_dateTimeEdit.dateTime().toString(fmt)
        qidx = self.cbox_query_type.currentIndex()
        ngok = self.qname1[qidx]
        self.running = 1
        find_file_by_time_fun = find_file_by_time
        if 'pathsavetype' in config:
            if 'hf'==config['pathsavetype']:
                find_file_by_time_fun = find_file_by_time_hf
        if 0:
            find_file_by_time_fun(self, time0, time1, ngok)
        else:
            self.ret = self.pool.submit(find_file_by_time_fun, self, time0, time1, ngok)
        return 0

    def query11(self):
        fmt = "yyyyMMdd_hhmmss"
        time0 = self.start_dateTimeEdit.dateTime().toString(fmt)
        time1 = self.end_dateTimeEdit.dateTime().toString(fmt)
        outp0 = get_outp0()
        li = listdirsub(outp0, '.jpg')
        # self.datastt.clear_data()
        ppp = {}
        fns = {}
        for fn in li:
            pa, fn1 = os.path.split(fn)
            pp = os.path.split(pa)[1]
            if pp not in ppp:
                ppp[pp] = [str('') for x in range(14)]
                fns[pp] = [['', ''] for x in cam_ips]
            fn0, ext = os.path.splitext(fn1)
            aa = '_'.join(fn0.split('_')[1:3])
            if aa <= time1 and aa >= time0:
                tiaoma, index, end = fn.split('_')[-4:-1]
                index1 = 4 + int(index)
                ppp[pp][0] = pp
                ppp[pp][2] = tiaoma
                t = ppp[pp][3]
                if 'NG' in [t, end]:
                    t = 'NG'
                else:
                    t = 'OK'
                ppp[pp][3] = t
                ppp[pp][4 + int(index)] = end
                t = 0
                if '_ret' in fn:
                    t = 1
                fns[pp][int(index)][t] = fn
                # ppp[pp].append(fn)
        self.pppp = []

        def netItem_clicked(iy, ix):
            index = ix - 4
            if index >= 0:
                fn2 = fns[pp][int(index)]
                print(iy, ix, fn2)
                # dialog = ShowInfo(self, self.out, irow)
                # dialog.setWindowTitle("详细信息")
                # dialog.setWindowModality(Qt.ApplicationModal)
                # dialog.exec_()
                self.show_img(fn2)
            return 0

        self.datastt.tableWidget.cellClicked.connect(netItem_clicked)
        for iy, pp in enumerate(ppp):
            xx = ppp[pp]
            items = self.datastt.add_data(xx)

        # self.update()
        # print(time0)
        return 0

    def show_img(self, li):
        # pa = r'D:\data\gree_zhuhai\2_d\images\train'
        # li = listdir(pa, '.jpg .png')
        # li = [f'{pa}/{x}' for x in li]
        for i in range(len(self.imglabs)):
            if i < len(li):
                if not os.path.exists(li[i]):
                    continue
                try:
                    img = cv_imread(li[i])
                except Exception as e:
                    continue
                showimg(self.imglabs[i], img)


def test_gui_database(ss=None):
    app = QApplication(sys.argv)
    ex = Ui_DataBase(ss)
    # ex.use_pass = 0
    # ex.setWindowTitle(config['classname'])
    # ex.setWindowTitle(config['checkname'])
    ex.showMaximized()
    ex.show()

    # ex.scadaSignal.emit(['asdfasdf'])
    # ex = Ui_Setting()
    sys.exit(app.exec_())
    return 0



if __name__ == "__main__":
    test_gui_database()
